package com.cdel.akka.coordinate;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.pattern.Patterns;
import akka.transactor.Coordinated;
import akka.util.Timeout;
import com.typesafe.config.ConfigFactory;
import scala.concurrent.Await;

import java.util.concurrent.TimeUnit;

/**
 * 软件事务内存：这里的事务和数据库的事务类似，具有隔离性、原子性和一致性。与数据库事务不同的是，内存事务不具有持久性。
 * 在很多场合，某一项工作需要多个actor合作完成，如果一个actor失败，根据事务的原子性，其它actor所进行的操作必须要回滚。
 * 假设公司给员工发工资业务，CompanyActor是公司actor， EmployeeActor是员工actor，公司账户减钱，员工账户加钱，这就要求事务。
 */
public class STMMain {
    public static ActorRef companyActor = null;
    public static ActorRef employeeActor = null;


    public static void main(String [] args) throws Exception {
        ActorSystem system = ActorSystem.create("stm", ConfigFactory.load("akka.conf"));
        companyActor = system.actorOf(Props.create(CompanyActor.class), "CompanyActor");
        employeeActor = system.actorOf(Props.create(EmployeeActor.class), "EmployeeActor");

        Timeout timeout = new Timeout(1, TimeUnit.SECONDS);

        for(int i = 0 ; i < 23; i ++){
        	//新建一个Coordinated协调者，并且将这个协调者当做消息发送给companyActor，当companyActor收到这个协调者消息后，自动成为这个事务的第一个成员。
            companyActor.tell(new Coordinated(10, timeout), ActorRef.noSender());

            Thread.sleep(200);

            int companyCount = (int) Await.result(Patterns.ask(companyActor, "getCount", timeout), timeout.duration());
            int employeeCount = (int) Await.result(Patterns.ask(employeeActor, "getCount", timeout), timeout.duration());

            System.out.println("companyCount = " + companyCount + ";employeeCount = " + employeeCount);
            System.out.println("-----------------------");
        }

    }
}